package com.cenntro.common.util;

import java.awt.Point;
import java.awt.geom.Point2D;
import java.math.RoundingMode;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.cenntro.common.httpclient.HttpsUtils;
import com.cenntro.common.util.BigDecimalUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;

/*
WGS-84：是国际标准，GPS坐标（Google Earth使用、或者GPS模块）
GCJ-02：中国坐标偏移标准，Google Map、高德、腾讯使用
BD-09：百度坐标偏移标准，Baidu Map使用

代码参考：http://bbs.lbsyun.baidu.com/forum.php?mod=viewthread&tid=10923
*/
public class GpsTrasformUtil {

	static double pi = 3.14159265358979324;
	static double a = 6378245.0;
	static double ee = 0.00669342162296594323;
	public final static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
	public static String ak = "bqk2EpTkvOe1CN1WeFEoVxFQ95fcavGN";   //百度ak
	
	public static Logger LOG = LoggerFactory.getLogger(GpsTrasformUtil.class);   //百度ak
	/**
	 * 
	 * @param lat
	 * @param lon
	 * @return double[]{lat,lng}
	 */
	public static double[] wgs2bd(double lat, double lon) {
		double[] wgs2gcj = wgs2gcj(lat, lon);
		double[] gcj2bd = gcj2bd(wgs2gcj[0], wgs2gcj[1]);
		return gcj2bd;
	}

	/**
	 * 
	 * @param lat
	 * @param lon
	 * @return
	 */
	public static double[] gcj2bd(double lat, double lon) {
		double x = lon, y = lat;
		double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
		double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
		double bd_lon = z * Math.cos(theta) + 0.0065;
		double bd_lat = z * Math.sin(theta) + 0.006;
		return new double[] { bd_lat, bd_lon };
	}

	public static double[] bd2gcj(double lat, double lon) {
		double x = lon - 0.0065, y = lat - 0.006;
		double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
		double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
		double gg_lon = z * Math.cos(theta);
		double gg_lat = z * Math.sin(theta);
		return new double[] { gg_lat, gg_lon };
	}

	public static double[] wgs2gcj(double lat, double lon) {
		double dLat = transformLat(lon - 105.0, lat - 35.0);
		double dLon = transformLon(lon - 105.0, lat - 35.0);
		double radLat = lat / 180.0 * pi;
		double magic = Math.sin(radLat);
		magic = 1 - ee * magic * magic;
		double sqrtMagic = Math.sqrt(magic);
		dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
		dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
		double mgLat = lat + dLat;
		double mgLon = lon + dLon;
		double[] loc = { mgLat, mgLon };
		return loc;
	}

	private static double transformLat(double lat, double lon) {
		double ret = -100.0 + 2.0 * lat + 3.0 * lon + 0.2 * lon * lon + 0.1 * lat * lon
				+ 0.2 * Math.sqrt(Math.abs(lat));
		ret += (20.0 * Math.sin(6.0 * lat * pi) + 20.0 * Math.sin(2.0 * lat * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(lon * pi) + 40.0 * Math.sin(lon / 3.0 * pi)) * 2.0 / 3.0;
		ret += (160.0 * Math.sin(lon / 12.0 * pi) + 320 * Math.sin(lon * pi / 30.0)) * 2.0 / 3.0;
		return ret;
	}

	private static double transformLon(double lat, double lon) {
		double ret = 300.0 + lat + 2.0 * lon + 0.1 * lat * lat + 0.1 * lat * lon + 0.1 * Math.sqrt(Math.abs(lat));
		ret += (20.0 * Math.sin(6.0 * lat * pi) + 20.0 * Math.sin(2.0 * lat * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(lat * pi) + 40.0 * Math.sin(lat / 3.0 * pi)) * 2.0 / 3.0;
		ret += (150.0 * Math.sin(lat / 12.0 * pi) + 300.0 * Math.sin(lat / 30.0 * pi)) * 2.0 / 3.0;
		return ret;
	}


	/*
	 * 求两点连线与y轴正坐标的夹角  左偏 负角度 右偏正角度
	 * @param p1 起始点
	 * @param p2 结束点
	 * @return
	 */
	public static Integer getAngle(Point2D p1, Point2D p2) {
		double radian = Math.atan2(p2.getY() - p1.getX(), p2.getX() - p1.getX());
		double angle =  radian*(180/Math.PI);
		return BigDecimalUtil.getBigDecimal(angle).setScale(0, RoundingMode.HALF_UP).intValue();
	}
	
//	/**
//	 * 经度在前，纬度在后，经纬度间以“,”分割，经纬度小数点后不要超过 6 位,
//	 * 请用"|"进行间隔，并且将 batch 参数设置为 true，最多支持传入 20 对坐标点
//	 * @return
//	 */
//	private String getParam(String[][] cood){
//		String param = "";
//		for(String[] c : cood){
//			param += "lng=" + c[0]+ "&lat" + c[1];
//		}
//		if (cood.length > 1){
//			param += "&batch=true";
//		}
//		return null;
//	}
//	private void getRestTemplate(){
//		RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(10000).setConnectTimeout(10000).setSocketTimeout(30000).build();
//        HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(config).setRetryHandler(new DefaultHttpRequestRetryHandler(5, false));
//        HttpClient httpClient = builder.build();
//        //使用httpClient创建一个ClientHttpRequestFactory的实现
//        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
//         //ClientHttpRequestFactory作为参数构造一个使用作为底层的RestTemplate
//        RestTemplate restTemplate = new RestTemplate(requestFactory);
//	}
	
	
	public static String[] gps2Address(String lng, String lat) {
		String coo = lat + "," + lng;
		String url = "http://api.map.baidu.com/geocoder/v2/?location=" + coo + "&output=json&pois=0&ak=" +  ak + "&coordtype=";
//		url = "https://restapi.amap.com/v3/geocode/geo?parameters"; 
//		url = "https://restapi.amap.com/v3/geocode/regeo?parameters";  //逆地址
		LOG.info("url: " + url);
			try {
				//阿里云地图调用(100代表道路，010代表兴趣点，001代表门址，111可以同时显示前三项)
					
//					URL url = new URL("http://api.map.baidu.com/geocoder/v2/?location=" + coo + "&output=json&pois=0&ak=" +  ak + "&coordtype="); //GET请求
//					ucon = (HttpURLConnection) url.openConnection();
//					ucon.connect();
//					in = ucon.getInputStream();
//					reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
//					String str = reader.readLine();
//					if(StringUtils.isNotBlank(str)) {
//						JSONObject jsonObject = JSONObject.parseObject(str);
//						if (jsonObject.getString("status").equals("0")){
//							JSONObject result = jsonObject.getJSONObject("result");
//							if(result != null){
//								String address = result.getString("sematic_description");
//								JSONObject addressComponent = result.getJSONObject("addressComponent");
//								String city = "";
//								if (addressComponent != null){
//									city  = addressComponent.getString("country") + " " 
//											+addressComponent.getString("province") + " " 
//											+addressComponent.getString("city") + " " 
//											+addressComponent.getString("district")+ " " ;
//								}
//								return new String []{city, address};
//							}
//						}
//					}
//				ucon.disconnect();
				String str = HttpsUtils.post(url, null, null, null);
				
//				HttpHeaders headers = new HttpHeaders();
//				headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
//				HttpEntity<String> requestEntity = new HttpEntity<String>("", headers);
//				//  执行HTTP请求
//				ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity , String.class );
//				String str = response.getBody();
				
				LOG.info("gps2Address: " + str);
				if(StringUtils.isNotBlank(str)) {
					JSONObject jsonObject = JSONObject.parseObject(str);
					if (jsonObject.getString("status").equals("0")){
						JSONObject result = jsonObject.getJSONObject("result");
						if(result != null){
							String address = result.getString("sematic_description");
							JSONObject addressComponent = result.getJSONObject("addressComponent");
							String city = "";
							if (addressComponent != null){
								city  = addressComponent.getString("country") + " " 
										+addressComponent.getString("province") + " " 
										+addressComponent.getString("city") + " " 
										+addressComponent.getString("district")+ " " ;
							}
							return new String []{city, address};
						}
					}
				}
			} catch (Exception e) {
				LOG.error("获取地址异常", e);
			} finally {
			}
			return null;
	}
	
}
